package org.tri.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.*;
import org.hibernate.Hibernate;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.Formula;

/**
 * La clase {@code Productor} almacena los datos pertinentes a un productor como asi tambien los establecimientos que posee
 * @author Lucas Giacomazzi
 * @version 1.0, Nov 16, 2011
 */
@Entity
@Table ( name = "productor" )
public class Productor implements Serializable {

    /** Identificador único del objeto. */
    private long idProductor;
    /** Cuit del productor. */
    private long cuit;
    /** Razón social del productor. */
    private String razonSocial;
    /** Domicilio del productor */
    private String domicilio;
    /** Localidad del domicilio del productor. */
    private String localidad;
    /** Teléfono del productor. */
    private long telefono;
    /** Tipo de documento del productor (o responsable). */
    private String tipoDocumento;
    /** Número de documento del productor (o responsable). */
    private long documento;
    /** Lista de establecimientos que pertenecen a este productor. */
    private List<Establecimiento> establecimientos = new ArrayList<Establecimiento>();
    /** Cantidad de establecimientos que pertenecen a este productor. */
    private int cantidadEstablecimientos;

    /**
     * Nos permite obtener el identificador utilizado por Hibernate de un productor
     * @return int identificador del productor
     */
    @Id
    @GeneratedValue ( strategy = GenerationType.IDENTITY )
    @Column ( name = "id_productor", nullable = false )
    public long getIdProductor() {
        return idProductor;

    }//end método getIdProductor

    /**
     * Nos permite modificar el identificador utilizado por Hibernate de un productor. 
     * Este método es de uso exclusivo de Hibernate. 
     * @param idProductor  identificador del productor a setear.
     */
    protected void setIdProductor( long idProductor ) {
        this.idProductor = idProductor;
    
    }//end método setIdProductor

    /**
     * Nos permite obtener el número de cuit que identifica a un productor.
     * @return cuit del productor.
     */
    @Column ( name = "cuit", nullable = false )
    public long getCuit() {
        return cuit;

    }//end método getCuit

    /**
     * Setea el cuit del productor.
     * @param cuit cuit a setear.
     */
    public void setCuit( long cuit ) {
        this.cuit = cuit;

    }//end método setCuit

    /**
     * Devuelve el número de documento del productor.
     * @return número de documento del productor.
     */
    @Column ( name = "documento" )
    public long getDocumento() {
        return documento;

    }//end método getDocumento

    /**
     * Setea el número de documento del productor.
     * @param documento número a setear.
     */
    public void setDocumento( long documento ) {
        this.documento = documento;

    }//end método setDocumento

    /**
     * Devuelve el domicilio del productor.
     * @return domicilio del productor.
     */
    @Column ( name = "domicilio", nullable = false, length = 60 )
    public String getDomicilio() {
        return domicilio;

    }//end método getDomicilio

    /**
     * Setea le domicilio del productor.
     * @param domicilio domicilio a setear.
     */
    public void setDomicilio( String domicilio ) {
        this.domicilio = domicilio;

    }//end método setDomicilio

    /**
     * Devuelve la localidad del domicilio del productor.
     * @return localidad del domicilio del productor.
     */
    @Column ( name = "localidad", nullable = false, length = 25 )
    public String getLocalidad() {
        return localidad;

    }//end método getLocalidad

    /**
     * Setea la localidad del domicilio del productor.
     * @param localidad localidad a setear.
     */
    public void setLocalidad( String localidad ) {
        this.localidad = localidad;

    }//end método setLocalidad

    /**
     * Devuelve la razón social del productor.
     * @return razón social del productor.
     */
    @Column ( name = "razon_social", nullable = false, length = 60 )
    public String getRazonSocial() {
        return razonSocial;

    }//end método getRazonSocial

    /**
     * Setea la razón social del productor.
     * @param razonSocial razón social a setear.
     */
    public void setRazonSocial( String razonSocial ) {
        this.razonSocial = razonSocial;

    }//end método setRazonSocial

    /**
     * Deuvelve el número de teléfono del productor.
     * @return número de teléfono del productor.
     */
    @Column ( name = "telefono" )
    public long getTelefono() {
        return telefono;

    }//end método getTelefono

    /**
     * Setea el número de teléfono del productor.
     * @param telefono numéro a setear.
     */
    public void setTelefono( long telefono ) {
        this.telefono = telefono;

    }//end método setTelefono

    /**
     * Devuelve el tipo de documento del productor o el 
     * responsable del negocio.
     * @return tipo de documento.
     */
    @Column ( name = "tipo_doc", length = 3 )
    public String getTipoDocumento() {
        return tipoDocumento;

    }//end método getTipoDocumento

    /**
     * Setea el tipo de documento del productor o el 
     * responsable del negocio.
     * @param tipoDocumento tipo de documento a setear.
     */
    public void setTipoDocumento( String tipoDocumento ) {
        this.tipoDocumento = tipoDocumento;

    }//end método setTipoDocumento

    /**
     * Devuelve la lista de establecimientos que pertenecen a 
     * este productor.
     * @return lista de establecimientos del productor.
     */
    @OneToMany ( cascade = { CascadeType.MERGE, CascadeType.PERSIST, 
                                                CascadeType.REFRESH }, 
                 mappedBy = "productor" )
    @Cascade ( { org.hibernate.annotations.CascadeType.SAVE_UPDATE,
                 org.hibernate.annotations.CascadeType.EVICT } )
    public List<Establecimiento> getEstablecimientos() {
        return establecimientos;

    }//end método getEstablecimientos   

    /**
     * Setea la lista de establecimientos del productor.
     * Este método es de uso exclusivo de hibernate para colocar
     * los datos de los establecimientos asociados obtenidos de
     * la base de datos.
     * @param establecimientos lista de establecimientos a setear.
     */
    protected void setEstablecimientos( List<Establecimiento> establecimientos ) {
        this.establecimientos = establecimientos;

    }//end método setEstablecimientos
    
    /**
     * Permite agregar un establecimiento a la lista de establecimientos
     * de este productor, en otras palabras, permite asignar el dueño 
     * a un establecimiento.
     * @param establecimiento establecimiento a agregar. 
     */
    public void agregarEstablecimiento( Establecimiento establecimiento ) {
        //seteamos el productor al establecimiento
        establecimiento.setProductor( this );
        
        //agregamos el establecimiento a la lista
        if ( Hibernate.isInitialized( establecimientos ) )
            establecimientos.add( establecimiento );
        
    }//end método agregarEstablecimiento
    
    /**
     * Permite quitar un establecimiento previamente asignado al productor.
     * @param establecimiento establecimiento a quitar.
     */
    public void quitarEstablecimiento( Establecimiento establecimiento ) {
        //comprobamos que el establecimiento pertenezca al productor
        if ( this.equals( establecimiento.getProductor() ) ) {
            //quitamos el productor del establecimiento
            establecimiento.setProductor( null );
            
            //quitamos el establecimiento de la lista de establecimientos
            if ( Hibernate.isInitialized( establecimientos ) )
                getEstablecimientos().remove( establecimiento );
            
        }//end if
        
    }//end método quitarEstablecimiento

    /**
     * Devuelva la cantidad de establecimientos que este productor posee.
     * @return cantidad de establecimientos del productor.
     */
    @Basic ( fetch = FetchType.LAZY )
    @Formula ( "(SELECT COUNT(e.renspa) FROM Establecimiento e WHERE e.productor = id_productor)" )
    public int getCantidadEstablecimientos() {
        return this.cantidadEstablecimientos;

    }//end método getCantidadEstablecimientos

    /**
     * Método utilizado por hibernate para setear la cantidad de
     * establecimientos.
     * @param cantidad cantidad de establecimientos a setear.
     */
    protected void setCantidadEstablecimientos( int cantidad ) {
        this.cantidadEstablecimientos = cantidad;

    }//end método setCantidadEstablecimientos

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals( Object obj ) {
        if ( obj == null )
            return false;
        if ( getClass() != obj.getClass() )
            return false;
        final Productor other = (Productor)obj;
        if ( this.cuit != other.cuit )
            return false;
        if ( ( this.razonSocial == null ) ? ( other.razonSocial != null ) : !this.razonSocial.equals( other.razonSocial ) )
            return false;
        return true;
        
    }//end método equals

    /**
     * Método estático que transforma el cuit de formato String a Long para ser
     * almacenado en la bd
     * @param cuit numero de cuit
     * @return cuit transformado a numeros
     */
    public static long cuitAsLong(String cuit){
        String resultado = "";
        String[] partes = cuit.split("-");
        
        for (String s: partes) {
            resultado += s;
            
        }
        
        return Long.parseLong(resultado);
        
    }
    
    /**
     * Método estático que transforma el cuit de formato long a String para ser
     * mostrado en la aplicacion
     * @param cuit numero de cuit
     * @return cuit transformado a numeros
     */
    public static String cuitAsString(long cuit){
        String original = String.valueOf(cuit);
        
        return String.format("%s-%s-%s", original.substring(0,2),
                                         original.substring(2,10),
                                         original.substring(10,11));
        
    }
    
    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        int hash = 3;
        hash = 97 * hash + (int)( this.cuit ^ ( this.cuit >>> 32 ) );
        hash = 97 * hash + ( this.razonSocial != null ? this.razonSocial.hashCode() : 0 );
        hash = 97 * hash + ( this.domicilio != null ? this.domicilio.hashCode() : 0 );
        hash = 97 * hash + ( this.localidad != null ? this.localidad.hashCode() : 0 );
        hash = 97 * hash + (int)( this.telefono ^ ( this.telefono >>> 32 ) );
        hash = 97 * hash + ( this.tipoDocumento != null ? this.tipoDocumento.hashCode() : 0 );
        hash = 97 * hash + (int)( this.documento ^ ( this.documento >>> 32 ) );
        return hash;
        
    }//end método hashCode
    
}//end clase Productor

